//-----------------------------------------------------------------------
// <copyright file="Installshield.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Andy Reeves</author>
// <email>andyr</email>
// <date>2004-03-23</date>
// <summary>Builds the specified Installshield project.</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.Tools
{
    using System;
    using System.Xml;
    using System.Globalization;
    using Microsoft.Win32;
    using System.IO;
    using Microsoft.Sdc.Tasks.Configuration;
    using Microsoft.Build.Framework;

    /// <summary>
    /// Builds the specified Installshield project.
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[
    /// <Tools.Installshield BuildPath="buildPath"
    ///              ProjectFilePath="projectFilePath"
    ///              ReleaseName="releaseName"
    ///              ReleaseConfiguration="releaseConfiguration"
    ///              WriteableDirectories="writeableDirectories" >
    /// </Tools.Installshield>
    /// ]]></code>
    /// <para>where:</para>
    /// <para><i>buildPath(Required)</i></para>
    /// <para>The fully qualified path to the folder where you want the output folders and files to be placed.</para>
    /// <para><i>projectFilePath</i></para>
    /// <para>The path to the .ism file that you would like to build. This path can be fully qualified, relative, or just the file name. If only the project file name is passed, the file is retrieved relative to the current working directory.</para>
    /// <para><i>releaseName</i></para>
    /// <para>The name of the release.</para>
    /// <para><i>releaseConfiguration</i></para>
    /// <para>This parameter allows you to specify whether you would like to have your release compressed into one file or remain uncompressed in multiple files. 
    /// The valid arguments for this parameter are "COMP" and "UNCOMP". To specify that your release be compressed into one file, use the "COMP" argument. If you do not want your release compressed, use the "UNCOMP" argument.
    /// This parameter is optional. If the release name already exists, the configuration will be based on what was specified in the IDE. If this is ignored for a new release, the new package will be uncompressed.</para>
    /// <para><i>writeableDirectories</i></para>
    /// <para>A list of directories for which all files within them are to be made writeable for use by InstallShield.</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <Tools.InstallShield
    ///              BuildPath="C:\InstallShieldOutput"
    ///              ProjectFilePath="C:\InstallShieldProjects\myProject.ism"
    ///              ReleaseName="Test"
    ///              ReleaseConfiguration="COMP" >
    ///         </Tools.InstallShield> 
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>

    public class Installshield : TaskBase
    {

        private string projectfilepath = String.Empty;
        private string releasename = String.Empty;
        private string releaseconfiguration = String.Empty;
        private string buildpath = String.Empty;
        private string[] writeableDirectories;

        /// <summary>
        /// Initializes a new instance of the Installshield class.
        /// </summary>
        public Installshield()
        {
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code

            Directory.CreateDirectory(buildpath);

            RegistryKey installShieldKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\InstallShield\Developer\7.0");

            string pathToInstallShield = Convert.ToString(installShieldKey.GetValue("Install Location"), CultureInfo.InvariantCulture);
            installShieldKey.Close();

            ShellExecute shellExecute = new ShellExecute();
            shellExecute.Filename = Path.Combine(pathToInstallShield, @"System\IsCmdBld.exe");
            Log.LogMessageFromResources("Installshield.BuildingPackage");

            this.MakeFilesWritable(writeableDirectories);

            string args = String.Format(CultureInfo.InvariantCulture, " -p {0} -r {1} -c {2} -b {3} -s", projectfilepath, releasename, releaseconfiguration, buildpath);
            shellExecute.Arguments = args;
            shellExecute.Execute();
            Log.LogMessageFromResources(MessageImportance.Low, "Installshield.PackageComplete");

            #endregion
        }

        /// <summary>
        /// Makes each file in each specified directory writeable.
        /// </summary>
        /// <param name="directories">The directories containing the files that are to be made writeable.</param>
        private void MakeFilesWritable(string[] directories)
        {
            if (directories != null)
            {
                foreach (string directory in directories)
                {
                    DirectoryInfo di = new DirectoryInfo(directory);
                    FileInfo[] files = di.GetFiles();
                    foreach (FileInfo file in files)
                    {
                        file.Attributes = FileAttributes.Normal;
                    }
                }
            }
        }

        /// <summary>
        /// The path to the .ism file that you would like to build. 
        /// </summary>
        /// <value>This path can be fully qualified, relative, or just the file name. If only the project file name is passed, the file is retrieved relative to the current working directory.</value>
        public string ProjectFilepath
        {
            get
            {
                return (projectfilepath == null ? String.Empty : projectfilepath);
            }
            set
            {
                projectfilepath = value;
            }
        }

        /// <summary>
        /// The name of the release.
        /// </summary>
        /// <value>The name of the release.</value>
        public string ReleaseName
        {
            get
            {
                return (releasename == null ? String.Empty : releasename);
            }
            set
            {
                releasename = value;
            }
        }

        /// <summary>
        /// This parameter allows you to specify whether you would like to have your release compressed into one file or remain uncompressed in multiple files. 
        /// </summary>
        /// <value>The valid arguments for this parameter are "COMP" and "UNCOMP". To specify that your release be compressed into one file, use the "COMP" argument. If you do not want your release compressed, use the "UNCOMP" argument.
        /// This parameter is optional. If the release name already exists, the configuration will be based on what was specified in the IDE. If this is ignored for a new release, the new package will be uncompressed.</value>
        public string ReleaseConfiguration
        {
            get
            {
                return (releaseconfiguration == null ? String.Empty : releaseconfiguration);
            }
            set
            {
                releaseconfiguration = value;
            }
        }

        /// <summary>
        /// The fully qualified path to the folder where you want the output folders and files to be placed.
        /// </summary>
        /// <value>The fully qualified path to the folder where you want the output folders and files to be placed.</value>
        [Required]
        public string BuildPath
        {
            get
            {
                return (buildpath == null ? String.Empty : buildpath);
            }
            set
            {
                buildpath = value;
            }
        }

        /// <summary>
        /// A list of directories for which all files within them are to be made writeable for use by InstallShield.
        /// </summary>
        /// <value>A list of directories for which all files within them are to be made writeable for use by InstallShield.</value>
        public string[] WriteableDirectories
        {
            get
            {
                return writeableDirectories;
            }
            set
            {
                writeableDirectories = value;
            }
        }


    }
}

